home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
gnuish
/
mkinf10
/
makeinfo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-01
|
48KB
|
1,683 lines
/* Makeinfo -- convert texinfo format files into info files
Copyright (C) 1987 Free Software Foundation, Inc.
This file is part of GNU Info.
Makeinfo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY. No author or distributor accepts
responsibility to anyone for the consequences of using it or for
whether it serves any particular purpose or works at all, unless he
says so in writing. Refer to the GNU Emacs General Public License
for full details.
Everyone is granted permission to copy, modify and redistribute
Makeinfo, but only under the conditions described in the GNU Emacs
General Public License. A copy of this license is supposed to
have been given to you along with GNU Emacs so you can know your
rights and responsibilities. It should be in a file named COPYING.
Among other things, the copyright notice and this notice must be
preserved on all copies. */
/* MS-DOS port (c) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet
This port is also distributed under the terms of the
GNU General Public License as published by the
Free Software Foundation.
Please note that this file is not identical to the
original GNU release, you should have received this
code as patch to the official release.
$Header: e:/gnu/info/RCS/makeinfo.c 0.1.1.1 90/10/05 11:25:23 tho Exp $
*/
/* **************************************************************** */
/* */
/* Include File Declarations */
/* */
/* **************************************************************** */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#ifndef MSDOS
#include <pwd.h>
#endif /* not MSDOS */
#ifdef MSDOS /* `16+4' bit machines... */
#define VOID void
#define PVOID void
#define SIZE_T size_t
#define LONG long
#if defined (_MSC_VER) && (_MSC_VER >= 600)
#define HUGE _huge
#define CDECL _cdecl
#else
#define HUGE huge
#define CDECL cdecl
#endif
#else /* not MSDOS */
#define VOID int
#define PVOID char
#define SIZE_T int
#define LONG int
#define HUGE
#define CDECL
#endif /* not MSDOS */
#ifdef MSDOS
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <malloc.h>
#include <io.h>
#include <dos.h>
char *msdos_format_filename (char *name);
void _huge *xhalloc (long size);
void _huge *xhrealloc (void _huge *ptr, long new_size, long old_size);
long hread (int fd, void _huge *buffer, long bytes);
char **args_from_string (char *string);
char *current_item_function (void);
char *defun_title (int type);
char *expand_filename (char *filename, char *input_name);
char *filename_part (char *filename);
char HUGE *find_and_load (char *filename);
char *find_proc_name (VOID (*proc) ());
char *full_pathname (char *filename);
char *get_item_function (void);
char *get_node_token (void);
char *get_xref_token (void);
char *insertion_type_pname (int type);
char *pathname_part (char *filename);
char *read_token (void);
char *reftype_type_string (int type);
PVOID *xmalloc (SIZE_T nbytes);
PVOID *xrealloc (PVOID *pointer, SIZE_T nbytes);
VOID add_char (int character);
VOID add_word (char *string);
VOID CDECL add_word_args (char *format, ...);
VOID begin_insertion (int type);
VOID canon_white (char *string);
VOID close_paragraph (void);
VOID close_paragraph_with_lines (int lines);
VOID close_single_paragraph (void);
VOID cm_appendix (void);
VOID cm_appendixsec (void);
VOID cm_appendixsubsec (void);
VOID cm_appendixsubsubsec (void);
VOID cm_asis (void);
VOID cm_asterisk (void);
VOID cm_bold (int arg);
VOID cm_br (void);
VOID cm_bullet (int arg);
VOID cm_bye (void);
VOID cm_center (void);
VOID cm_chapter (void);
VOID cm_cindex (void);
VOID cm_cite (int arg, int position);
VOID cm_code (int arg);
VOID cm_comment (void);
VOID cm_copyright (int arg);
VOID cm_ctrl (int arg, int position);
VOID cm_defindex (void);
VOID cm_defun (void);
VOID cm_dfn (int arg, int position);
VOID cm_display (void);
VOID cm_dots (int arg);
VOID cm_emph (int arg);
VOID cm_end (void);
VOID cm_enumerate (void);
VOID cm_equiv (int arg);
VOID cm_error (int arg);
VOID cm_example (void);
VOID cm_exdent (void);
VOID cm_expansion (int arg);
VOID cm_file (int arg);
VOID cm_findex (void);
VOID cm_footnote (void);
VOID cm_force_abbreviated_whitespace (void);
VOID cm_force_sentence_end (void);
VOID cm_format (void);
VOID cm_group (void);
VOID cm_ifinfo (void);
VOID cm_iftex (void);
VOID cm_ignore (void);
VOID cm_include (void);
VOID cm_infoinclude (void);
VOID cm_inforef (int arg);
VOID cm_italic (int arg);
VOID cm_item (void);
VOID cm_itemize (void);
VOID cm_itemx (void);
VOID cm_kbd (int arg);
VOID cm_key (int arg);
VOID cm_kindex (void);
VOID cm_lisp (void);
VOID cm_menu (void);
VOID cm_minus (int arg);
VOID cm_need (void);
VOID cm_node (void);
VOID cm_noindent (void);
VOID cm_obsolete (int arg);
VOID cm_pindex (void);
VOID cm_point (int arg);
VOID cm_print (int arg);
VOID cm_printindex (void);
VOID cm_pxref (int arg);
VOID cm_quotation (void);
VOID cm_refill (void);
VOID cm_result (int arg);
VOID cm_roman (int arg);
VOID cm_samp (int arg);
VOID cm_sc (int arg, int start_pos, int end_pos);
VOID cm_section (void);
VOID cm_setchapternewpage (void);
VOID cm_setfilename (void);
VOID cm_settitle (void);
VOID cm_smallexample (void);
VOID cm_sp (void);
VOID cm_strong (int arg, int position);
VOID cm_subsection (void);
VOID cm_subsubsection (void);
VOID cm_synindex (void);
VOID cm_table (void);
VOID cm_TeX (int arg);
VOID cm_tex (void);
VOID cm_tindex (void);
VOID cm_title (int arg);
VOID cm_titlepage (void);
VOID cm_titlespec (void);
VOID cm_unnumbered (void);
VOID cm_unnumberedsec (void);
VOID cm_unnumberedsubsec (void);
VOID cm_unnumberedsubsubsec (void);
VOID cm_var (int arg, int start_pos, int end_pos);
VOID cm_vindex (void);
VOID cm_w (int arg);
VOID cm_xref (int arg);
VOID convert (char *name);
int current_insertion_type (void);
VOID defindex (char *name);
VOID define_alias (char *alias, char *function);
VOID define_user_command (char *name, VOID (*proc) (), int needs_braces_p);
int defun_insertion (int type);
VOID defun_internal (int type, char *title, int x_p);
VOID discard_braces (void);
VOID discard_insertions (void);
VOID discard_until (char *string);
VOID do_nothing (void);
VOID end_insertion (int type);
int CDECL error (char *format, ...);
VOID CDECL execute_string (char *format, ...);
int find_index_offset (char *name);
int find_type_from_name (char *name);
VOID fix_whitespace (char *string);
VOID flush_file_stack (void);
VOID flush_output (void);
VOID free_and_clear (char **pointer);
VOID free_index (struct index_elt * index);
VOID free_node_references (void);
VOID free_pending_notes (void);
int fs_error (char *filename);
VOID gen_index (void);
int get_char_len (int character);
VOID get_defun_args (void);
VOID get_rest_of_line (char **string);
VOID get_until (char *match, char **string);
VOID get_until_in_braces (char *match, char **string);
VOID get_until_in_line (char *match, char **string);
VOID glean_node_from_menu (void);
VOID indent (int amount);
VOID index_add_arg (char *name);
int CDECL index_element_compare (struct index_elt **element1,
struct index_elt **element2);
VOID init_brace_stack (void);
VOID init_indices (void);
VOID init_insertion_stack (void);
VOID init_internals (void);
VOID init_paragraph (void);
VOID init_tag_table (void);
VOID insert (int character);
VOID insert_and_underscore (int with_char);
VOID insert_defun_arg (char *string, int where);
VOID insert_self (void);
VOID kill_self_indent (int count);
int CDECL line_error (char *format, ...);
VOID CDECL main (int argc, char **argv);
VOID misplaced_brace (void);
VOID normalize_node_name (char *string);
VOID number_item (void);
VOID output_pending_notes (void);
VOID popfile (void);
int pop_and_call_brace (void);
VOID pop_insertion (void);
VOID pop_node_filename (void);
VOID pushfile (void);
VOID push_insertion (int type, char *item_function);
VOID push_node_filename (void);
VOID reader_loop (void);
VOID read_command (void);
VOID remember_brace (VOID (*proc) ());
VOID remember_brace_1 (VOID (*proc) (), LONG position);
VOID remember_error (void);
VOID remember_node (char *node, char *prev, char *next, char *up,
LONG position, int line_no, int no_warn);
VOID remember_node_reference (char *node, int line, int type);
VOID remember_note (char *marker, char *note);
LONG search_forward (char *string, LONG from);
int self_delimiting (int character);
VOID set_footnote_style (char *string);
VOID split_file (char *filename, LONG size);
VOID start_numbering (int at_number);
VOID start_paragraph (void);
VOID stop_numbering (void);
int translate_index (char *name);
int undefindex (char *name);
VOID usage (void);
int validate (char *tag, int line, char *label);
VOID validate_file (char *filename, struct tentry * tag_table);
VOID validate_other_references (struct node_ref * ref_list);
int CDECL warning (char *format, ...);
int what_section (char *text);
int write_tag_table (void);
int write_tag_table_indirect (void);
VOID write_tag_table_internal (int indirect_p);
struct generic_list *reverse_list (struct generic_list * list);
struct index_elt **sort_index (struct index_elt * index);
struct index_elt *index_append (struct index_elt * head,
struct index_elt * tail);
struct index_elt *index_list (char *name);
struct node_ref *find_node_reference (char *node, struct node_ref * ref_list);
struct tentry *find_node (char *name);
#endif /* MSDOS */
#include "getopt.h"
#ifdef SYSV
#include <string.h>
struct passwd *getpwnam ();
#include <fcntl.h>
#define bcopy(source, dest, count) memcpy (dest, source, count)
#define index strchr
#else
#include <strings.h>
#include <sys/file.h>
#endif
#if defined (sparc) || defined (i386)
#ifndef __GNUC__
#include <alloca.h>
#else
#define alloca __builtin_alloca
#endif
#endif
/* Forward declarations. */
PVOID *xmalloc (), *xrealloc ();
/* **************************************************************** */
/* */
/* Global Defines */
/* */
/* **************************************************************** */
/* Error levels */
#define NO_ERROR 0
#define SYNTAX 1
#define FATAL 2
/* Boolean values. */
#define true 1
#define false 0
typedef int boolean;
/* I want to make sure that NULL looks like this. */
#ifdef NULL
#undef NULL
#endif
#define NULL 0x0
/* How to allocate permanent storage for STRING. */
#define savestring(x) \
((char *)strcpy (xmalloc (1 + ((x) ? strlen (x) : 0)), (x) ? (x) : ""))
/* C's standard macros don't check to make sure that the characters being
changed are within range. So I have to check explicitly. */
/* GNU Library doesn't have toupper(). Until GNU gets this fixed, I will
have to do it. */
#ifndef toupper
#define toupper(c) ((c) - 32)
#endif
#define coerce_to_upper(c) ((islower(c) ? toupper(c) : (c)))
#define coerce_to_lower(c) ((isupper(c) ? tolower(c) : (c)))
#define control_character_bit 0x40 /* %01000000, must be off. */
#define meta_character_bit 0x080/* %10000000, must be on. */
#define CTL(c) ((c) & (~control_character_bit))
#define UNCTL(c) coerce_to_upper(((c)|control_character_bit))
#define META(c) ((c) | (meta_character_bit))
#define UNMETA(c) ((c) & (~meta_character_bit))
#define whitespace(c) (((c) == '\t') || ((c) == ' '))
#define sentence_ender(c) ((c) == '.' || (c) == '?' || (c) == '!')
#define cr_or_whitespace(c) (((c) == '\t') || ((c) == ' ') || ((c) == '\n'))
#define member(c, s) (index (s, c) != NULL)
#define COMMAND_PREFIX '@'
/* Stuff for splitting large files. */
#ifdef MSDOS
#define SPLIT_SIZE_THRESHOLD 60000 /* What's good enough for Stallman... */
#define DEFAULT_SPLIT_SIZE 40000 /* Is not good enough for me. */
#else /* not MSDOS */
#define SPLIT_SIZE_THRESHOLD 70000 /* What's good enough for Stallman... */
#define DEFAULT_SPLIT_SIZE 50000/* Is probably good enough for me. */
#endif /* not MSDOS */
boolean splitting = true; /* Always true for now. */
typedef VOID FUNCTION (); /* So I can say FUNCTION *foo; */
/* **************************************************************** */
/* */
/* Global Variables */
/* */
/* **************************************************************** */
/* Global pointer to argv[0]. */
char *progname;
/* The current input file state. */
char *input_filename;
char HUGE *input_text;
LONG size_of_input_text;
LONG input_text_offset;
int line_number;
#define curchar() input_text[input_text_offset]
#define command_char(c) ((!whitespace(c)) && \
((c) != '\n') && \
((c) != '{'))
#define skip_whitespace() while (input_text_offset != size_of_input_text \
&& whitespace(curchar()))\
input_text_offset++
/* And writing to the output. */
/* The output file name. */
char *output_filename, *pretty_output_filename;
/* Current output stream. */
FILE *output_stream;
/* Position in the output file. */
LONG output_position;
/* Output paragraph buffer. */
char *output_paragraph;
/* Offset into OUTPUT_PARAGRAPH. */
int output_paragraph_offset;
/* The output paragraph "cursor" horizontal position. */
int output_column = 0;
/* non-zero means output_paragraph contains text. */
boolean paragraph_is_open = false;
#define INITIAL_PARAGRAPH_SPACE 5000
int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
/* Filling.. */
/* True indicates that filling will take place on long lines. */
boolean filling_enabled = true;
/* Non-zero means that words are not to be split, even in long lines. This
gets changed for cm_w (). */
int non_splitting_words = 0;
/* True indicates that filling a line also indents the new line. */
boolean indented_fill = false;
/* The column at which long lines are broken. */
int fill_column = 72;
/* The amount of indentation to apply at the start of each line. */
int current_indent = 0;
/* The amount of indentation to add at the starts of paragraphs.
0 means don't change existing indentation at paragraph starts.
> 0 is amount to indent new paragraphs by.
< 0 means indent to column zero by removing indentation if necessary.
This is normally zero, but some people prefer paragraph starts to be
somewhat more indented than paragraph bodies. A pretty value for
this is 3. */
int paragraph_start_indent = 0;
/* Non-zero means that the use of paragraph_start_indent is inhibited.
@example uses this to line up the left columns of the example text. */
int inhibit_paragraph_indentation = 0;
/* Indentation that is pending insertion. We have this for hacking lines
which look blank, but contain whitespace. We want to treat those as
blank lines. */
int pending_indent = 0;
/* The amount that indentation increases/decreases by. */
int default_indentation_increment = 5;
/* True indicates that indentation is temporarily turned off. */
boolean no_indent = true;
/* Command name in the process of being hacked. */
char *command;
/* The index in our internal command table of the currently
executing command. */
int command_index;
/* A stack of file information records. If a new file is read in with
"@input", we remember the old input file state on this stack. */
typedef struct fstack
{
struct fstack *next;
char *filename;
char *text;
LONG size;
LONG offset;
int line_number;
} FSTACK;
FSTACK *filestack = (FSTACK *) NULL;
/* Stuff for nodes. */
/* The current nodes node name */
char *current_node;
/* The current nodes section level. */
int current_section = 0;
/* The filename of the current input file. This is never freed. */
char *node_filename = (char *)NULL;
/* What we remember for each node. */
typedef struct tentry
{
struct tentry *next_ent;
char *node; /* name of this node. */
char *prev; /* name of "Prev:" for this node. */
char *next; /* name of "Next:" for this node. */
char *up; /* name of "Up:" for this node. */
LONG position; /* output file position of this node. */
int line_no; /* defining line in source file. */
char *filename; /* The file that this node was found in. */
int touched; /* non-zero means this node has been referenced. */
int flags; /* Room for growth. Right now, contains 1 bit. */
} TAG_ENTRY;
/* If node-a has a "Next" for node-b, but node-b has no "Prev" for node-a,
we turn on this flag bit in node-b's tag entry. This means that when
it is time to validate node-b, we don't report an additional error
if there was no "Prev" field. */
#define PREV_ERROR 0x1
#define NEXT_ERROR 0x2
#define UP_ERROR 0x4
#define NO_WARN 0x8
TAG_ENTRY *tag_table = (TAG_ENTRY *) NULL;
/* Menu reference, *note reference, and validation hacking. */
/* The various references that we know about. */
enum reftype
{
menu_reference, followed_reference
};
/* A structure to remember references with. A reference to a node is
either an entry in a menu, or a cross-reference made with [px]ref. */
typedef struct node_ref
{
struct node_ref *next;
char *node; /* Name of node referred to. */
char *containing_node; /* Name of node containing this reference. */
int line_no; /* Line number where the reference occurs. */
int section; /* Section level where the reference occurs. */
char *filename; /* Name of file where the reference occurs. */
enum reftype type; /* Type of reference, either menu or note. */
} NODE_REF;
/* The linked list of such structures. */
NODE_REF *node_references = (NODE_REF *) NULL;
/* Flag which tells us whether to examine menu lines or not. */
int in_menu = 0;
/* Flags controlling the operation of the program. */
/* Default is to notify users of bad choices. */
boolean print_warnings = true;
/* Default is to check node references. */
boolean validating = true;
/* Number of errors that we tolerate on a given fileset. */
int max_error_level = 100;
/* Maximum number of references to a single node before complaining. */
int reference_warning_limit = 1000;
/* Non-zero means print out information about what is going on when it
is going on. */
int verbose_mode = 0;
/* The list of commands that we hack in texinfo. Each one
has an associated function. When the command is encountered in the
text, the associated function is called with START as the argument.
If the function expects arguments in braces, it remembers itself on
the stack. When the corresponding close brace is encountered, the
function is called with END as the argument. */
#define START 0
#define END 1
typedef struct brace_element
{
struct brace_element *next;
FUNCTION *proc;
LONG pos;
int line;
} BRACE_ELEMENT;
BRACE_ELEMENT *brace_stack = (BRACE_ELEMENT *) NULL;
/* Forward declarations. */
VOID
insert_self (), cm_tex (), cm_asterisk (), cm_dots (), cm_bullet (),
cm_TeX (), cm_copyright (), cm_code (), cm_samp (), cm_file (), cm_kbd (),
cm_key (), cm_ctrl (), cm_var (), cm_dfn (), cm_emph (), cm_strong (),
cm_cite (), cm_italic (), cm_bold (), cm_roman (), cm_title (), cm_w (),
cm_refill ();
VOID
cm_chapter (), cm_unnumbered (), cm_appendix (),
cm_section (), cm_unnumberedsec (), cm_appendixsec (),
cm_subsection (), cm_unnumberedsubsec (), cm_appendixsubsec (),
cm_subsubsection (), cm_unnumberedsubsubsec (), cm_appendixsubsubsec ();
/* All @defxxx commands map to cm_defun (). */
VOID
cm_defun ();
VOID
cm_node (), cm_menu (), cm_xref (),
cm_pxref (), cm_inforef (), cm_quotation (), cm_display (), cm_itemize (),
cm_enumerate (), cm_table (), cm_itemx (), cm_noindent (), cm_setfilename (),
cm_comment (), cm_ignore (), cm_br (), cm_sp (), cm_page (), cm_group (),
cm_need (), cm_center (), cm_include (), cm_bye (), cm_item (), cm_end (),
cm_infoinclude (), cm_ifinfo (), cm_iftex (), cm_titlepage (),
cm_titlespec (),cm_kindex (), cm_cindex (), cm_findex (), cm_pindex (),
cm_vindex (), cm_tindex (), cm_asis (), cm_synindex (), cm_settitle (),
cm_setchapternewpage (), cm_printindex (), cm_minus (), cm_footnote (),
cm_force_abbreviated_whitespace (), cm_force_sentence_end (), cm_example (),
cm_smallexample (), cm_lisp (), cm_format (), cm_exdent (), cm_defindex (),
cm_sc (), cm_result (), cm_expansion (), cm_equiv (), cm_print (),
cm_error (), cm_point ();
VOID do_nothing ();
VOID misplaced_brace (), cm_obsolete ();
typedef struct
{
char *name;
FUNCTION *proc;
boolean argument_in_braces;
} COMMAND;
#ifdef MSDOS
COMMAND *get_command_entry (char *string);
#endif /* MSDOS */
/* Stuff for defining commands on the fly. */
COMMAND **user_command_array = (COMMAND **) NULL;
int user_command_array_len = 0;
static COMMAND CommandTable[] = {
{"!", cm_force_sentence_end, false},
{"'", insert_self, false},
{"*", cm_asterisk, false},
{".", cm_force_sentence_end, false},
{":", cm_force_abbreviated_whitespace, false},
{"?", cm_force_sentence_end, false},
{"@", insert_self, false},
{" ", insert_self, false},
{"\n", insert_self, false},
{"TeX", cm_TeX, true},
{"`", insert_self, false},
{"appendix", cm_appendix, false},
{"appendixsec", cm_appendixsec, false},
{"appendixsubsec", cm_appendixsubsec, false},
{"appendixsubsubsec", cm_appendixsubsubsec, false},
{"asis", cm_asis, true},
{"b", cm_bold, true},
{"br", cm_br, false},
{"bullet", cm_bullet, true},
{"bye", cm_bye, false},
{"c", cm_comment, false},
{"center", cm_center, false},
{"chapter", cm_chapter, false},
{"cindex", cm_cindex, false},
{"cite", cm_cite, true},
{"code", cm_code, true},
{"comment", cm_comment, false},
{"contents", do_nothing, false},
{"copyright", cm_copyright, true},
{"ctrl", cm_ctrl, true},
{"defcodeindex", cm_defindex, false},
{"defindex", cm_defindex, false},
{"dfn", cm_dfn, true},
/* The `def' commands. */
{"defun", cm_defun, false},
{"defunx", cm_defun, false},
{"defvar", cm_defun, false},
{"defvarx", cm_defun, false},
{"defopt", cm_defun, false},
{"defoptx", cm_defun, false},
{"deffn", cm_defun, false},
{"deffnx", cm_defun, false},
{"defspec", cm_defun, false},
{"defspecx", cm_defun, false},
{"defmac", cm_defun, false},
{"defmacx", cm_defun, false},
/* The end of the `def' commands. */
{"display", cm_display, false},
{"dots", cm_dots, true},
{"emph", cm_emph, true},
{"end", cm_end, false},
{"enumerate", cm_enumerate, false},
{"equiv", cm_equiv, true},
{"error", cm_error, true},
{"example", cm_example, false},
{"exdent", cm_exdent, false},
{"expansion", cm_expansion, true},
{"file", cm_file, true},
{"findex", cm_findex, false},
{"format", cm_format, false},
{"group", cm_group, false},
{"i", cm_italic, true},
{"iappendix", cm_appendix, false},
{"iappendixsec", cm_appendixsec, false},
{"iappendixsubsec", cm_appendixsubsec, false},
{"iappendixsubsubsec", cm_appendixsubsubsec, false},
{"ichapter", cm_chapter, false},
{"ifinfo", cm_ifinfo, false},
{"iftex", cm_iftex, false},
{"ignore", cm_ignore, false},
{"include", cm_include, false},
{"inforef", cm_inforef, true},
{"input", cm_include, false},
{"isection", cm_section, false},
{"isubsection", cm_subsection, false},
{"isubsubsection", cm_subsubsection, false},
{"item", cm_item, false},
{"itemize", cm_itemize, false},
{"itemx", cm_itemx, false},
{"iunnumbered", cm_unnumbered, false},
{"iunnumberedsec", cm_unnumberedsec, false},
{"iunnumberedsubsec", cm_unnumberedsubsec, false},
{"iunnumberedsubsubsec", cm_unnumberedsubsubsec, false},
{"kbd", cm_kbd, true},
{"key", cm_key, true},
{"kindex", cm_kindex, false},
{"lisp", cm_lisp, false},
{"menu", cm_menu},
{"minus", cm_minus, true},
{"need", cm_need, false},
{"node", cm_node, false},
{"noindent", cm_noindent, false},
{"page", do_nothing, false},
{"pindex", cm_pindex, false},
{"point", cm_point, true},
{"print", cm_print, true},
{"printindex", cm_printindex, false},
{"pxref", cm_pxref, true},
{"quotation", cm_quotation, false},
{"r", cm_roman, true},
{"ref", cm_xref, true},
{"refill", cm_refill, false},
{"result", cm_result, true},
{"samp", cm_samp, true},
{"sc", cm_sc, true},
{"section", cm_section, false},
{"setchapternewpage", cm_setchapternewpage, false},
{"setfilename", cm_setfilename, false},
{"settitle", cm_settitle, false},
{"smallexample", cm_smallexample, false},
{"sp", cm_sp, false},
{"strong", cm_strong, true},
{"subsection", cm_subsection, false},
{"subsubsection", cm_subsubsection, false},
{"summarycontents", do_nothing, false},
{"syncodeindex", cm_synindex, false},
{"synindex", cm_synindex, false},
{"t", cm_title, true},
{"table", cm_table, false},
{"tex", cm_tex, false},
{"tindex", cm_tindex, false},
{"titlepage", cm_titlepage, false},
{"titlespec", cm_titlespec, false},
{"unnumbered", cm_unnumbered, false},
{"unnumberedsec", cm_unnumberedsec, false},
{"unnumberedsubsec", cm_unnumberedsubsec, false},
{"unnumberedsubsubsec", cm_unnumberedsubsubsec, false},
{"var", cm_var, true},
{"vindex", cm_vindex, false},
{"w", cm_w, true},
{"xref", cm_xref, true},
{"{", insert_self, false},
{"}", insert_self, false},
/* Now @include does what this was supposed to. */
{"infoinclude", cm_infoinclude, false},
{"footnote", cm_footnote, false}, /* self-arg eater */
{(char *) NULL, (FUNCTION *) NULL}, false};
/* Non-zero means we are running inside of Emacs. */
int in_emacs = 0;
#ifndef MAKEINFO_MAJOR
#define MAKEINFO_MAJOR 1
#endif
#ifndef MAKEINFO_MINOR
#define MAKEINFO_MINOR 0
#endif
int major_version = MAKEINFO_MAJOR;
int minor_version = MAKEINFO_MINOR;
struct option long_options[] =
{
{ "no-validate", 0, &validating, false }, /* formerly -nv */
{ "no-warn", 0, &print_warnings, false }, /* formerly -nw */
{ "no-split", 0, &splitting, false }, /* formerly -ns */
{ "verbose", 0, &verbose_mode, 1 }, /* formerly -verbose */
{ "fill-column", 1, 0, 'f' }, /* formerly -fc */
{ "paragraph-indent", 1, 0, 'p' }, /* formerly -pi */
{ "error-limit", 1, 0, 'e' }, /* formerly -el */
{ "reference-limit", 1, 0, 'r' }, /* formerly -rl */
{ "footnote-style", 1, 0, 's' }, /* formerly -ft */
{ "version", 0, 0, 'V' },
{NULL, 0, NULL, 0}
};
/* **************************************************************** */
/* */
/* Main () Start of code */
/* */
/* **************************************************************** */
/* For each file mentioned in the command line, process it, turning
texinfo commands into wonderfully formatted output text. */
VOID CDECL
main (argc, argv)
int argc;
char **argv;
{
char *t = (char *) getenv ("EMACS");
int c;
int ind;
progname = argv[0];
if (t && strcmp (t, "t") == 0)
in_emacs++;
/* Parse argument flags from the input line. */
while ((c = getopt_long (argc, argv, "", long_options, &ind)) != EOF)
{
if (c == 0 && long_options[ind].flag == 0)
c = long_options[ind].val;
switch (c)
{
case 'f':
/* user specified fill_column? */
if (sscanf (optarg, "%d", &fill_column) != 1)
usage ();
break;
case 'p':
/* User specified paragraph indent (paragraph_start_index)? */
if (sscanf (optarg, "%d", ¶graph_start_indent) != 1)
usage ();
break;
case 'e':
/* User specified error level? */
if (sscanf (optarg, "%d", &max_error_level) != 1)
usage ();
break;
case 'r':
/* User specified reference warning limit? */
if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
usage ();
break;
case 's':
/* User specified footnote style? */
set_footnote_style (optarg);
break;
case 'V': /* Use requested version info? */
fprintf (stderr, "Makeinfo verison %d.%d.\n",
major_version, minor_version);
exit (0);
break;
case '?':
usage ();
}
}
if (optind == argc)
usage ();
/* Remaining arguments are file names of texinfo files.
Convert them, one by one. */
while (optind != argc)
convert (argv[optind++]);
exit (0);
}
/* **************************************************************** */
/* */
/* Generic Utilities */
/* */
/* **************************************************************** */
/* Just like malloc, but kills the program in case of fatal error. */
PVOID *
xmalloc (nbytes)
SIZE_T nbytes;
{
PVOID *temp = (PVOID *) malloc (nbytes);
if (temp == (PVOID *) NULL)
{
error ("Virtual memory exhausted! Needed %d bytes.", nbytes);
exit (FATAL);
}
return (temp);
}
/* Like realloc (), but barfs if there isn't enough memory. */
PVOID *
xrealloc (pointer, nbytes)
PVOID *pointer;
SIZE_T nbytes;
{
pointer = (PVOID *) realloc (pointer, nbytes);
if (!pointer)
{
error ("Virtual memory exhausted in realloc ().");
abort ();
}
return (pointer);
}
/* Tell the user how to use this program. */
VOID
usage ()
{
fprintf (stderr, "Usage: %s [options] texinfo-file...\n\
\n\
This program accepts as input files of texinfo commands and text\n\
and outputs a file suitable for reading with GNU Info.\n\
\n\
The options are:\n\
`+no-validate' to suppress node cross reference validation.\n\
`+no-warn' to suppress warning messages (errors are still output).\n\
`+no-split' to suppress the splitting of large files.\n\
`+verbose' to print information about what is being done.\n\
`+version' to print the version number of Makeinfo.\n\
`+paragraph-indent NUM' to set the paragraph indent to NUM (default %d).\n\
`+fill-column NUM' to set the filling column to NUM (default %d).\n\
`+error-limit NUM' to set the error limit to NUM (default %d).\n\
`+reference-limit NUM' to set the reference warning limit to NUM (default %d).\n\
`+footnote-style STYLE' to set the footnote style to STYLE. STYLE should\n\
either be `MN' for `make node', or `BN' for `bottom node'.\n\n",
progname, paragraph_start_indent,
fill_column, max_error_level, reference_warning_limit);
exit (2);
}
/* **************************************************************** */
/* */
/* Manipulating Lists */
/* */
/* **************************************************************** */
typedef struct generic_list
{
struct generic_list *next;
} GENERIC_LIST;
/* Reverse the chain of structures in LIST. Output the new head
of the chain. You should always assign the output value of this
function to something, or you will lose the chain. */
GENERIC_LIST *
reverse_list (list)
register GENERIC_LIST *list;
{
register GENERIC_LIST *next;
register GENERIC_LIST *prev = (GENERIC_LIST *) NULL;
while (list)
{
next = list->next;
list->next = prev;
prev = list;
list = next;
}
return (prev);
}
/* **************************************************************** */
/* */
/* Pushing and Popping Files */
/* */
/* **************************************************************** */
/* Find and load the file named FILENAME. Return a pointer to
the loaded file, or NULL if it can't be loaded. */
char HUGE *
find_and_load (filename)
char *filename;
{
#ifdef MSDOS
long bytes_read;
#endif /* MSDOS */
struct stat fileinfo;
int file;
char HUGE *result = (char HUGE *) NULL;
if ((stat (filename, &fileinfo)) != 0)
goto error_exit;
file = open (filename, O_RDONLY);
if (file < 0)
goto error_exit;
/* Load the file. */
#ifdef MSDOS
result = xhalloc (fileinfo.st_size);
bytes_read = hread (file, result, fileinfo.st_size);
if (bytes_read <= 0L)
#else /* not MSDOS */
result = xmalloc (fileinfo.st_size);
if (read (file, result, fileinfo.st_size) != fileinfo.st_size)
#endif /* not MSDOS */
error_exit:
{
if (result)
#ifdef MSDOS
hfree (result);
#else /* not MSDOS */
free (result);
#endif /* not MSDOS */
if (file != -1)
close (file);
return ((char *) NULL);
}
close (file);
/* Set the globals to the new file. */
input_text = result;
#ifdef MSDOS
size_of_input_text = bytes_read;
#else /* not MSDOS */
size_of_input_text = fileinfo.st_size;
#endif /* not MSDOS */
input_filename = savestring (filename);
node_filename = savestring (filename);
input_text_offset = 0;
line_number = 1;
return (result);
}
/* Save the state of the current input file. */
VOID
pushfile ()
{
FSTACK *newstack = (FSTACK *) xmalloc (sizeof (FSTACK));
newstack->filename = input_filename;
newstack->text = input_text;
newstack->size = size_of_input_text;
newstack->offset = input_text_offset;
newstack->line_number = line_number;
newstack->next = filestack;
filestack = newstack;
push_node_filename ();
}
/* Make the current file globals be what is on top of the file stack. */
VOID
popfile ()
{
extern int executing_string;
FSTACK *temp = filestack;
if (!filestack)
abort (); /* My fault. I wonder what I did? */
/* Make sure that commands with braces have been satisfied. */
if (!executing_string)
discard_braces ();
/* Get the top of the stack into the globals. */
input_filename = filestack->filename;
input_text = filestack->text;
size_of_input_text = filestack->size;
input_text_offset = filestack->offset;
line_number = filestack->line_number;
/* Pop the stack. */
filestack = filestack->next;
free (temp);
pop_node_filename ();
}
/* Flush all open files on the file stack. */
VOID
flush_file_stack ()
{
while (filestack)
{
free (input_filename);
free (input_text);
popfile ();
}
}
int node_filename_stack_index = 0;
int node_filename_stack_size = 0;
char **node_filename_stack = (char **)NULL;
VOID
push_node_filename ()
{
if (node_filename_stack_index + 1 > node_filename_stack_size)
{
if (!node_filename_stack)
node_filename_stack =
(char **)xmalloc ((node_filename_stack_size += 10)
* sizeof (char *));
else
node_filename_stack =
(char **)xrealloc (node_filename_stack,
(node_filename_stack_size + 10)
* sizeof (char *));
}
node_filename_stack[node_filename_stack_index] = node_filename;
node_filename_stack_index++;
}
VOID
pop_node_filename ()
{
node_filename = node_filename_stack[--node_filename_stack_index];
}
/* Return just the simple part of the filename; i.e. the
filename without the path information, or extensions.
This conses up a new string. */
char *
filename_part (filename)
char *filename;
{
register int i = strlen (filename) - 1;
while (i && filename[i] != '/')
i--;
if (filename[i] == '/')
i++;
#ifdef REMOVE_OUTPUT_EXTENSIONS
result = savestring (&filename[i]);
/* See if there is an extension to remove. If so, remove it. */
if (rindex (result, '.'))
*(rindex (result, '.')) = '\0';
return (result);
#else
return (savestring (&filename[i]));
#endif /* REMOVE_OUTPUT_EXTENSIONS */
}
/* Return the pathname part of filename. This can be NULL. */
char *
pathname_part (filename)
char *filename;
{
char *expand_filename ();
char *result = (char *) NULL;
register int i;
filename = expand_filename (filename, "");
i = strlen (filename) - 1;
while (i && filename[i] != '/')
i--;
if (filename[i] == '/')
i++;
if (i)
{
result = xmalloc (1 + i);
strncpy (result, filename, i);
result[i] = '\0';
}
free (filename);
return (result);
}
/* Return the expansion of FILENAME. */
char *
expand_filename (filename, input_name)
char *filename, *input_name;
{
char *full_pathname ();
filename = full_pathname (filename);
if (filename[0] == '.')
return (filename);
if (filename[0] != '/' && input_name[0] == '/')
{
/* Make it so that relative names work. */
char *result = xmalloc (1 + strlen (input_name)
+ strlen (filename));
int i = strlen (input_name) - 1;
strcpy (result, input_name);
while (result[i] != '/' && i)
i--;
if (result[i] == '/')
i++;
strcpy (&result[i], filename);
free (filename);
return (result);
}
return (filename);
}
/* Return the full path to FILENAME. */
char *
full_pathname (filename)
char *filename;
{
int initial_character;
if (filename && (initial_character = *filename))
{
if (initial_character == '/')
return (savestring (filename));
if (initial_character != '~')
{
return (savestring (filename));
}
else
{
if (filename[1] == '/')
{
/* Return the concatenation of HOME and the rest of the string. */
char *temp_home = (char *) getenv ("HOME");
char *temp_name = xmalloc (strlen (&filename[2])
+ 1
+ temp_home ? strlen (temp_home)
: 0);
if (temp_home)
strcpy (temp_name, temp_home);
strcat (temp_name, &filename[2]);
return (temp_name);
}
else
{
#ifdef MSDOS
return (savestring (filename));
#else /* not MSDOS */
struct passwd *user_entry;
int i, c;
char *username = xmalloc (257);
char *temp_name;
for (i = 1; c = filename[i]; i++)
{
if (c == '/')
break;
else
username[i - 1] = c;
}
if (c)
username[i - 1] = '\0';
user_entry = getpwnam (username);
if (!user_entry)
return (savestring (filename));
temp_name = xmalloc (1 + strlen (user_entry->pw_dir)
+ strlen (&filename[i]));
strcpy (temp_name, user_entry->pw_dir);
strcat (temp_name, &filename[i]);
return (temp_name);
#endif /* not MSDOS */
}
}
}
else
{
return (savestring (filename));
}
}
/* **************************************************************** */
/* */
/* Error Handling */
/* */
/* **************************************************************** */
/* Number of errors encountered. */
int errors_printed = 0;
/* Print the last error gotten from the file system. */
fs_error (filename)
char *filename;
{
perror (filename);
return ((int) false);
}
/* Print an error message, and return false. */
#ifdef MSDOS
int CDECL
error (char *format, ...)
{
va_list arg_ptr;
va_start (arg_ptr, format);
remember_error ();
vfprintf (stderr, format, arg_ptr);
fprintf (stderr, "\n");
return ((int) false);
}
#else /* not MSDOS */
error (format, arg1, arg2, arg3, arg4, arg5)
char *format;
{
remember_error ();
fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
fprintf (stderr, "\n");
return ((int) false);
}
#endif /* not MSDOS */
/* Just like error (), but print the line number as well. */
#ifdef MSDOS
int CDECL
line_error (char *format, ...)
{
va_list arg_ptr;
va_start (arg_ptr, format);
remember_error ();
fprintf (stderr, "%s:%d: ", input_filename, line_number);
vfprintf (stderr, format, arg_ptr);
fprintf (stderr, ".\n");
return ((int) false);
}
#else /* not MSDOS */
line_error (format, arg1, arg2, arg3, arg4, arg5)
char *format;
{
remember_error ();
fprintf (stderr, "%s:%d: ", input_filename, line_number);
fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
fprintf (stderr, ".\n");
return ((int) false);
}
#endif /* not MSDOS */
#ifdef MSDOS
int CDECL
warning (char *format, ...)
{
if (print_warnings)
{
va_list arg_ptr;
va_start (arg_ptr, format);
fprintf (stderr, "%s:%d: Warning: ", input_filename, line_number);
vfprintf (stderr, format, arg_ptr);
fprintf (stderr, ".\n");
}
return ((int) false);
}
#else /* not MSDOS */
warning (format, arg1, arg2, arg3, arg4, arg5)
char *format;
{
if (print_warnings)
{
fprintf (stderr, "%s:%d: Warning: ", input_filename, line_number);
fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
fprintf (stderr, ".\n");
}
return ((int) false);
}
#endif /* not MSDOS */
/* Remember that an error has been printed. If this is the first
error printed, then tell them which program is printing them.
If more than max_error_level have been printed, then exit the
program. */
VOID
remember_error ()
{
errors_printed++;
if (max_error_level && (errors_printed > max_error_level))
{
fprintf (stderr, "Too many errors! Gave up.");
flush_file_stack ();
cm_bye ();
}
}
/* **************************************************************** */
/* */
/* Hacking Tokens and Strings */
/* */
/* **************************************************************** */
/* Return the next token as a string pointer. We cons the
string. */
char *
read_token ()
{
int i, character;
char *result;
/* Hack special case. If the first character to be read is
self-delimiting, then that is the command itself. */
character = curchar ();
if (self_delimiting (character))
{
input_text_offset++;
result = savestring (" ");
*result = character;
return (result);
}
for (i = 0; ((input_text_offset != size_of_input_text)
&& (character = curchar ())
&& command_char (character));
i++, input_text_offset++);
result = xmalloc (i + 1);
strncpy (result, &input_text[input_text_offset - i], i);
result[i] = '\0';
return (result);
}
/* Return TRUE if CHARACTER is self-delimiting. */
boolean
self_delimiting (character)
int character;
{
return (member (character, "{}:.@*'`,!?; \n"));
}
/* Clear whitespace from the front and end of string. */
VOID
canon_white (string)
char *string;
{
int len = strlen (string);
int x;
if (!len)
return;
for (x = 0; x < len; x++)
{
if (!whitespace (string[x]))
{
strcpy (string, string + x);
break;
}
}
len = strlen (string);
if (len)
len--;
while (len > -1 && cr_or_whitespace (string[len]))
len--;
string[len + 1] = '\0';
}
/* Bash STRING, replacing all whitespace with just one space. */
VOID
fix_whitespace (string)
char *string;
{
char *temp = xmalloc (strlen (string) + 1);
int string_index = 0;
int temp_index = 0;
int c;
canon_white (string);
while (string[string_index])
{
c = temp[temp_index++] = string[string_index++];
if (c == ' ' || c == '\n' || c == '\t')
{
temp[temp_index - 1] = ' ';
while ((c = string[string_index]) && (c == ' ' ||
c == '\t' ||
c == '\n'))
string_index++;
}
}
temp[temp_index] = '\0';
strcpy (string, temp);
free (temp);
}
/* Discard text until the desired string is found. The string is
included in the discarded text. */
VOID
discard_until (string)
char *string;
{
LONG temp = search_forward (string, input_text_offset);
LONG tt = (temp < 0) ? size_of_input_text : temp + strlen (string);
LONG from = input_text_offset;
/* Find out what line we are on. */
while (from != tt)
if (input_text[from++] == '\n')
line_number++;
if (temp < 0)
{
input_text_offset = size_of_input_text - strlen (string);
if (strcmp (string, "\n") != 0)
{
line_error ("Expected `%s'", string);
return;
}
}
else
input_text_offset = temp;
input_text_offset += strlen (string);
}
/* Read characters from the file until we are at MATCH.
Place the characters read into STRING.
On exit input_text_offset is after the match string.
Return the length of STRING. */
VOID
get_until (match, string)
char *match, **string;
{
SIZE_T len;
LONG current_point = input_text_offset;
LONG x = current_point;
LONG new_point = search_forward (match, input_text_offset);
if (new_point < 0)
new_point = size_of_input_text;
#ifdef MSDOS
assert (new_point - current_point < (1L<<16));
len = (size_t) (new_point - current_point);
#else /* not MSDOS */
len = new_point - current_point;
#endif /* not MSDOS */
/* Keep track of which line number we are at. */
while (x != new_point)
if (input_text[x++] == '\n')
line_number++;
*string = xmalloc (len + 1);
strncpy (*string, &input_text[current_point], len);
(*string)[len] = '\0';
/* Now leave input_text_offset in a consistent state. */
input_text_offset = new_point + (strlen (match) - 1);
if (input_text_offset > size_of_input_text)
input_text_offset = size_of_input_text;
}
/* Read characters from the file until we are at MATCH or end of line.
Place the characters read into STRING. */
VOID
get_until_in_line (match, string)
char *match, **string;
{
LONG real_bottom = size_of_input_text;
LONG temp = search_forward ("\n", input_text_offset);
if (temp < 0)
temp = size_of_input_text;
size_of_input_text = temp;
get_until (match, string);
size_of_input_text = real_bottom;
}
VOID
get_rest_of_line (string)
char **string;
{
get_until ("\n", string);
canon_white (*string);
if (curchar () == '\n')
{ /* as opposed to the end of the file... */
line_number++;
input_text_offset++;
}
}
/* Read characters from the file until we are at MATCH or closing brace.
Place the characters read into STRING. */
VOID
get_until_in_braces (match, string)
char *match, **string;
{
LONG i;
int brace = 0;
int match_len = strlen (match);
char *temp;
for (i = input_text_offset; i < size_of_input_text; i++)
{
if (input_text[i] == '{')
brace++;
if (input_text[i] == '}')
brace--;
if (input_text[i] == '\n')
line_number++;
if (brace < 0 ||
(brace == 0 && strncmp (input_text + i, match, match_len) == 0))
break;
}
#ifdef MSDOS
assert (i - input_text_offset < (1L<<16));
match_len = (size_t) (i - input_text_offset);
#else /* not MSDOS */
match_len = i - input_text_offset;
#endif /* not MSDOS */
temp = xmalloc (2 + match_len);
strncpy (temp, input_text + input_text_offset, match_len);
temp[match_len] = '\0';
input_text_offset = i;
*string = temp;
}
/*===(cut here)===*/
/* Include the rest: */
#include "makeinfo.d"
#include "makeinfo.e"
/*
* Local Variables:
* mode:C
* ChangeLog:ChangeLog
* End:
*/